package cn.wolfcode.job;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.CommonCodeMsg;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.SeckillProductVo;
import cn.wolfcode.redis.JobRedisKey;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.web.feign.SeckillFeignApi;
import com.alibaba.fastjson.JSON;
import com.dangdang.ddframe.job.api.ShardingContext;
import com.dangdang.ddframe.job.api.simple.SimpleJob;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.prefs.BackingStoreException;
import java.util.stream.Collectors;

/**
 * 用于处理用户缓存的定时任务
 * 为了保证Redis中的内存的有效使用。
 * 我们默认保留7天内的用户缓存数据，每天凌晨的时候会把7天前的用户登录缓存数据删除掉
 */
@Component
@Setter
@Getter
@RefreshScope
@Slf4j
public class SeckillWarmUpJob implements SimpleJob {
    @Value("${jobCron.SeckillWarmUpJob}")
    private String cron;
    @Autowired
    private StringRedisTemplate redisTemplate;

    @Resource
    private SeckillFeignApi seckillFeignApi;

    @Override
    public void execute(ShardingContext shardingContext) {
        doWork();
    }

    private void doWork() {
        System.err.println("SeckillWarmUpJob...");
        //1 删除redis历史秒杀商品信息
        Integer[] times = {10, 12, 14};    //定义秒杀场次
        //List<前缀+time>
        List<String> seckillProductVoList = Arrays.stream(times).map(
                        new Function<Integer, String>() {
                            @Override
                            public String apply(Integer time) {
                                return SeckillRedisKey.SECKILL_PRODUCT_HASH.getRealKey(time.toString());
                            }
                        })
                .collect(Collectors.toList());
        redisTemplate.delete(seckillProductVoList);
        //删除库存
        List<String> seckillStockVoList = Arrays.stream(times).map(
                        time -> SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(time.toString()))
                .collect(Collectors.toList());
        redisTemplate.delete(seckillStockVoList);

        //2 从秒杀服务中获取当天的秒杀商品信息
        Result<List<SeckillProductVo>> result = seckillFeignApi.queryAllCurrent();
        //null 服务降级,  hasError ,对方抛异常
        if (StringUtils.isEmpty(result) || result.hasError()) {
            throw new BusinessException(CommonCodeMsg.RESULT_IS_EMPTY);
        }

        if (StringUtils.isEmpty(result.getData()) || result.getData().size() == 0) {
            return;
        }
        //3 把秒杀商品信息存入redis中
        //Map<Integer, List<SeckillProductVo>> collect
        result.getData().stream().collect(Collectors.groupingBy(vo -> vo.getTime())).forEach((k, v) -> {
            //处理vo
            String seckillBigKey = SeckillRedisKey.SECKILL_PRODUCT_HASH.getRealKey(k.toString());
            Map<String, String> voMap = v.stream().collect(Collectors.toMap(v2 -> String.valueOf(v2.getId()), v2 -> JSON.toJSONString(v2)));
            redisTemplate.opsForHash().putAll(seckillBigKey, voMap);

            //库存
            String storeBigKey = SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(k.toString());
            Map<String, String> storeMap =
                    v.stream().collect(
                            Collectors.toMap(
                                    v2 -> String.valueOf(v2.getId()), v2 -> v2.getStockCount().toString()));
            redisTemplate.opsForHash().putAll(storeBigKey, storeMap);
        });


//        result.getData().stream().forEach(vo -> {
//            //VO
//            String seckillBigKey = SeckillRedisKey.SECKILL_PRODUCT_HASH.getRealKey(vo.getTime().toString());
//            //store
//            String storeBigKey = SeckillRedisKey.SECKILL_STOCK_COUNT_HASH.getRealKey(vo.getTime().toString());
//            //smallKey
//            String smallKey = String.valueOf(vo.getId());
//
//            redisTemplate.opsForHash().put(seckillBigKey, smallKey, JSON.toJSONString(vo));
//            redisTemplate.opsForHash().put(storeBigKey, smallKey, String.valueOf(vo.getStockCount()));
//
//        });
    }


}
